{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Log模块资料\n",
    "- https://www.cnblogs.com/yyds/p/6901864.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python语言的高级特性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数式编程(FunctionalProgramming)\n",
    "- 基于lambda演算的一种编程方式\n",
    "    - 程序中只有函数\n",
    "    - 函数可以作为参数，同样可以作为返回值\n",
    "    - 纯函数式编程语言： LISP， Haskell\n",
    "    \n",
    "- Python函数式编程只是借鉴函数式编程的一些特点，可以理解成一半函数式一半Python\n",
    "- 需要讲述\n",
    "    - 高阶函数\n",
    "    - 返回函数\n",
    "    - 匿名函数\n",
    "    - 装饰器\n",
    "    - 偏函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  lambda表达式\n",
    "- 函数： 最大程度复用代码\n",
    "    - 存在问题： 如果函数很小，很短，则会造成啰嗦\n",
    "    - 如果函数被调用次数少，则会造成浪费\n",
    "    - 对于阅读者来说，造成阅读流程的被迫中断\n",
    "   \n",
    "- lambda表达式（匿名函数）：\n",
    "    - 一个表达式，函数体相对简单\n",
    "    - 不是一个代码块，仅仅是一个表达式\n",
    "    - 可以有参数，有多个参数也可以，用逗号隔开"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AAAAAAAA\n"
     ]
    }
   ],
   "source": [
    "# “小”函数举例\n",
    "def printA():\n",
    "    print(\"AAAAAAAA\")\n",
    "    \n",
    "    \n",
    "printA()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8900"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# lambda表达式的用法\n",
    "# 1. 以lambda开头\n",
    "# 2. 紧跟一定的参数（如果有的话）\n",
    "# 3. 参数后用冒号和表达式主题隔开\n",
    "# 4. 只是一个表达式，所以，没有return\n",
    "\n",
    "# 计算一个数字的100倍数\n",
    "# 因为就是一个表达式，所以没有return\n",
    "stm = lambda x: 100 * x \n",
    "# 使用上跟函数调用一模一样\n",
    "stm(89)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "654"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stm2 = lambda x,y,z: x+ y*10 + z*100\n",
    "stm2(4,5,6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 高阶函数\n",
    "- 把函数作为参数使用的函数，叫高阶函数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 变量可以赋值\n",
    "a = 100\n",
    "b = a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In funA\n"
     ]
    }
   ],
   "source": [
    "# 函数名称就是一个变量\n",
    "def funA():\n",
    "    print(\"In funA\")\n",
    "    \n",
    "funB = funA\n",
    "funB()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 以上代码得出的结论：\n",
    "- 函数名称是变量\n",
    "- funB 和 funA只是名称不一样而已\n",
    "- 既然函数名称是变量，则应该可以被当做参数传入另一个函数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2700\n",
      "2700\n",
      "210\n"
     ]
    }
   ],
   "source": [
    "# 高阶函数举例\n",
    "# funA是普通函数，返回一个传入数字的100倍数字\n",
    "\n",
    "def funA(n):\n",
    "    return n * 100\n",
    "\n",
    "# 再写一个函数，把传入参数乘以300倍，\n",
    "def funB(n ):\n",
    "    # 最终是想返回300n\n",
    "    return funA(n) * 3\n",
    "\n",
    "print(funB(9))\n",
    "\n",
    "# 写一个高阶函数\n",
    "def funC(n, f):\n",
    "    # 假定函数是把n扩大100被\n",
    "    return f(n) * 3\n",
    "\n",
    "print( funC(9, funA) )\n",
    "\n",
    "# 比较funC和funB, 显然funC的写法要优于funB\n",
    "# 例如：\n",
    "def funD(n):\n",
    "    return n*10\n",
    "\n",
    "# 需求变更，需要把n放大三十倍，此时funB则无法实现\n",
    "print(funC(7, funD))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  系统高阶函数-map\n",
    "- 原意就是映射，即把集合或者列表的元素，每一个元素都按照一定规则进行操作，生成一个新的列表或者集合\n",
    "- map函数是系统提供的具有映射功能的函数，返回值是一个迭代对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]\n",
      "0\n",
      "10\n",
      "20\n",
      "30\n",
      "40\n",
      "50\n",
      "60\n",
      "70\n",
      "80\n",
      "90\n",
      "[]\n"
     ]
    }
   ],
   "source": [
    "# map举例\n",
    "# 有一个列表，想对列表里的每一个元素乘以10， 并得到新的列表\n",
    "\n",
    "l1 = [i for i in range(10)]\n",
    "print(l1)\n",
    "l2 = []\n",
    "for i in l1:\n",
    "    l2.append(i * 10)\n",
    "\n",
    "print(l2)\n",
    "\n",
    "\n",
    "# 利用map实现\n",
    "def mulTen(n):\n",
    "    return n*10\n",
    "\n",
    "\n",
    "\n",
    "l3 = map(mulTen, l1 )\n",
    "# map类型是一个可迭代的结构，所以可以使用for遍历\n",
    "for i in l3:\n",
    "    print(i)\n",
    "  \n",
    "# 以下列表生成式得到的结果为空， why？\n",
    "l4 = [i for i in l3]\n",
    "print(l4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### reduce \n",
    "- 原意是归并，缩减\n",
    "- 把一个可迭代对象最后归并成一个结果\n",
    "- 对于作为参数的函数要求： 必须由两个参数，必须由返回结果\n",
    "- reduce([1,2,3,4,5]) == f( f(f(f(1,2),3), 4),5)\n",
    "- reduce 需要导入functools包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "21\n"
     ]
    }
   ],
   "source": [
    "from functools import reduce\n",
    "\n",
    "# 定义一个操作函数\n",
    "# 加入操作函数只是相加\n",
    "def myAdd(x,y):\n",
    "    return x + y\n",
    "    \n",
    "# 对于列表[1,2,3,4,5,6]执行myAdd的reduce操作\n",
    "rst = reduce( myAdd, [1,2,3,4,5,6] )\n",
    "print(rst)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### filter 函数\n",
    "- 过滤函数： 对一组数据进行过滤，符合条件的数据会生成一个新的列表并返回\n",
    "- 跟map相比较：\n",
    "    - 相同：都对列表的每一个元素逐一进行操作\n",
    "    - 不同：\n",
    "        - map会生成一个跟原来数据想对应的新队列\n",
    "        - filter不一定，只要符合条件的才会进入新的数据集合\n",
    "    - filter函数怎么写：\n",
    "        - 利用给定函数进行判断\n",
    "        - 返回值一定是个布尔值\n",
    "        - 调用格式： filter(f, data), f是过滤函数， data是数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'filter'>\n",
      "<filter object at 0x7f503403df60>\n",
      "[4, 56, 2, 4556, 4, 4]\n"
     ]
    }
   ],
   "source": [
    "# filter案例\n",
    "# 对于一个列表，对其进行过滤，偶数组成一个新列表\n",
    "\n",
    "# 需要定义过滤函数\n",
    "# 过滤函数要求有输入，返回布尔值\n",
    "def isEven(a):\n",
    "    return a % 2 == 0\n",
    "\n",
    "l = [3,4,56,3,2,3,4556,67,4,4,3,23455,43]\n",
    "\n",
    "rst = filter(isEven, l)\n",
    "# 返回的filter内容是一个可迭代对象\n",
    "print(type(rst))\n",
    "print(rst)\n",
    "\n",
    "print([i for i in rst])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 高阶函数-排序\n",
    "- 把一个序列按照给定算法进行排序\n",
    "- key: 在排序钱对每一个元素进行key函数运算，可以理解成按照key函数定义的逻辑进行排序\n",
    "- python2 和 python3 相差巨大"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[66723, 22312, 234, 123, 45, 43, 34, 3, 2]\n"
     ]
    }
   ],
   "source": [
    "# 排序的案例\n",
    "\n",
    "a = [234,22312,123,45,43,2,3,66723,34]\n",
    "al = sorted(a, reverse=True)\n",
    "print(al)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-4345, 45, -43, 23, -23, 6, 2]\n"
     ]
    }
   ],
   "source": [
    "# 排序案例2\n",
    "\n",
    "a = [-43,23,45,6,-23,2,-4345]\n",
    "# 按照绝对值进行排序\n",
    "# abs是求绝对值的意思\n",
    "# 即按照绝对值的倒叙排列\n",
    "al = sorted(a, key=abs, reverse=True)\n",
    "\n",
    "print(al)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Danaa', 'dana', 'haha', 'jingjing', 'wangxiaojing']\n",
      "['dana', 'Danaa', 'haha', 'jingjing', 'wangxiaojing']\n"
     ]
    }
   ],
   "source": [
    "# sorted案例\n",
    "\n",
    "astr = ['dana', 'Danaa', 'wangxiaojing', 'jingjing', 'haha']\n",
    "\n",
    "str1 = sorted(astr)\n",
    "print(str1)\n",
    "\n",
    "str2 = sorted(astr, key=str.lower)\n",
    "print(str2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 返回函数\n",
    "- 函数可以返回具体的值\n",
    "- 也可以返回一个函数作为结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 定义一个普通函数\n",
    "\n",
    "def myF(a):\n",
    "    print('In myF')\n",
    "    return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In myF\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "a = myF(8)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 函数作为返回值返回， 被返回的函数在函数体内定义\n",
    "\n",
    "def myF2():\n",
    "    \n",
    "    def myF3():\n",
    "        print(\"In myF3\")\n",
    "        return 3\n",
    "    return myF3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'function'>\n",
      "<function myF2.<locals>.myF3 at 0x7f5034036e18>\n",
      "In myF3\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用上面定义\n",
    "# 调用myF2， 返回一个函数myF3，赋值给f3\n",
    "f3 = myF2()\n",
    "print(type(f3))\n",
    "print(f3)\n",
    "\n",
    "f3()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 负责一点的返回函数的例子\n",
    "# args:参数列表\n",
    "# 1 myF4定义函数，返回内部定义的函数myF5\n",
    "# 2. myF5使用了外部变量，这个变量是myF4的参数\n",
    "\n",
    "def myF4( *args):\n",
    "    def myF5():\n",
    "        rst = 0\n",
    "        for n in args:\n",
    "            rst += n\n",
    "        return rst\n",
    "    return myF5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f5 = myF4(1,2,3,4,5,6,7,8,9,0)\n",
    "# f5的调用方式\n",
    "f5()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "150"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f6 = myF4(10,20,30,40,50)\n",
    "# f5的调用方式\n",
    "f6()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 闭包（closure)\n",
    "- 当一个函数在内部定义函数，并且内部的函数应用外部函数的参数或者局部变量，当内部函数被当做返回值的时候，相关参数和变量保存在返回的函数中，这种结果，叫闭包\n",
    "- 上面定义的myF4是一个标准闭包结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9\n",
      "9\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "# 闭包常见坑\n",
    "def count():\n",
    "    # 定义列表，列表里存放的是定义的函数\n",
    "    fs = []\n",
    "    for i in range(1,4):\n",
    "        # 定义了一个函数f\n",
    "        # f是一个闭包结构\n",
    "        def f():\n",
    "            return i*i\n",
    "        fs.append(f)\n",
    "    return fs\n",
    "\n",
    "f1,f2,f3 = count()\n",
    "print(f1())\n",
    "print(f2())\n",
    "print(f3())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 出现的问题：\n",
    "- 造成上述状况的原因是,返回函数引用了变量i， i并非立即执行，而是等到三个函数都返回的时候才统一使用，此时i已经变成了3，最终调用的时候，都返回的是 3*3\n",
    "- 此问题描述成：返回闭包时，返回函数不能引用任何循环变量\n",
    "- 解决方案： 再创建一个函数，用该函数的参数绑定循环变量的当前值，无论该循环变量以后如何改变，已经绑定的函数参数值不再改变"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "4\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# 修改上述函数\n",
    "def count2():\n",
    "    def f(j):\n",
    "        def g():\n",
    "            return j*j\n",
    "        return g\n",
    "    fs = []\n",
    "    for i in range(1,4):\n",
    "        fs.append(f(i))\n",
    "    return fs\n",
    "\n",
    "f1,f2,f3 = count2()\n",
    "print(f1())\n",
    "print(f2())\n",
    "print(f3())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world\n"
     ]
    }
   ],
   "source": [
    "def hello():\n",
    "    print(\"Hello world\")\n",
    "    \n",
    "hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world\n"
     ]
    }
   ],
   "source": [
    "f = hello\n",
    "f()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "139982101828744\n",
      "139982101828744\n",
      "hello\n",
      "hello\n"
     ]
    }
   ],
   "source": [
    "# f和hello是一个函数\n",
    "print(id(f)) \n",
    "print(id(hello))\n",
    "\n",
    "print(f.__name__)\n",
    "print(f.__name__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 现在由新的需求：\n",
    "# 对hello功能进行扩展，每次打印hello之前打印当前系统时间\n",
    "# 而实现这个功能又不能改动现有代码\n",
    "# ==>使用装饰器\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器(Decrator)\n",
    "- 在不改动函数代码的基础上无限制扩展函数功能的一种机制，本质上讲，装饰器是一个返回函数的高阶函数\n",
    "- 装饰器的使用： 使用@语法， 即在每次要扩展到函数定义前使用@+函数名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 任务：\n",
    "# 对hello函数进行功能扩展，每次执行hello万打印当前时间\n",
    "\n",
    "import time\n",
    "\n",
    "# 高阶函数，以函数作为参数\n",
    "def printTime(f):\n",
    "    def wrapper(*args, **kwargs):\n",
    "        print(\"Time: \", time.ctime())\n",
    "        return f(*args, **kwargs)\n",
    "    return wrapper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time:  Mon Apr  2 21:14:52 2018\n",
      "Hello world\n"
     ]
    }
   ],
   "source": [
    "# 上面定义了装饰器，使用的时候需要用到@， 此符号是python的语法糖\n",
    "@printTime\n",
    "def hello():\n",
    "    print(\"Hello world\")\n",
    "    \n",
    "hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time:  Mon Apr  2 21:17:50 2018\n",
      "今天很高兴，被老板揪着讲课了\n",
      "还可以由很多的选择\n"
     ]
    }
   ],
   "source": [
    "# 装饰器的好处是，一点定义，则可以装饰任意函数\n",
    "# 一旦被其装饰，则则把装饰器的功能直接添加到定义函数的功能上\n",
    "\n",
    "@printTime\n",
    "def hello2():\n",
    "    print(\"今天很高兴，被老板揪着讲课了\")\n",
    "    print(\"还可以由很多的选择\")\n",
    "\n",
    "hello2()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我是手动执行的\n",
      "Time:  Mon Apr  2 21:22:39 2018\n",
      "我是手动执行的\n",
      "Time:  Mon Apr  2 21:22:39 2018\n",
      "Time:  Mon Apr  2 21:22:39 2018\n",
      "我是手动执行的\n"
     ]
    }
   ],
   "source": [
    "# 上面对函数的装饰使用了系统定义的语法糖\n",
    "# 下面开始手动执行下装饰器\n",
    "# 先定义函数\n",
    "\n",
    "def hello3():\n",
    "    print(\"我是手动执行的\")\n",
    "    \n",
    "hello3()\n",
    "\n",
    "hello3 = printTime(hello3)\n",
    "hello3()\n",
    "\n",
    "f = printTime(hello3)\n",
    "f()\n",
    "# 作业：\n",
    "# 解释下面的执行结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 偏函数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5349"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 把字符串转化成十进制数字\n",
    "int(\"12345\")\n",
    "\n",
    "# 求八进制的字符串12345，表示成十进制的数字是多少\n",
    "int(\"12345\", base=8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "74565"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 新建一个函数，此函数是默认输入的字符串是16进制数字\n",
    "# 把此字符串返回十进制的数字\n",
    "def int16(x, base=16):\n",
    "    return int(x, base)\n",
    "\n",
    "int16(\"12345\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 偏函数\n",
    "- 参数固定的函数，相当于一个由特定参数的函数体\n",
    "- functools.partial的作用是，把一个函数某些函数固定，返回一个新函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "74565"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import functools\n",
    "#实现上面int16的功能\n",
    "int16 = functools.partial(int, base=16)\n",
    "\n",
    "int16(\"12345\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
